package org.teamswift.crow.rbac.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.teamswift.crow.rbac.entity.CrowPermissionResource;
import org.teamswift.crow.rest.exception.BusinessException;
import org.teamswift.crow.rest.utils.CrowResourceUtils;
import org.teamswift.crow.rest.utils.DozerUtils;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Data
public class CrowPermissionResourceService {

    private Set<CrowPermissionResource> permissionResources = new HashSet<>();

    private Map<String, CrowPermissionResource> permissionResourcesMap = new HashMap<>();

    private Logger logger = LoggerFactory.getLogger(getClass());

    private String permissionResourceSaveFile = "permissionResource.json";

    private final ObjectMapper objectMapper;

    public CrowPermissionResourceService(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
        this.refreshPermissionResources();
    }

    /**
     * Refresh the permission resources saved in permissionResourceSaveFile.json.
     */
    public void refreshPermissionResources() {
        InputStream in;
        try {
            in = CrowResourceUtils.getResourceFile(permissionResourceSaveFile);
        } catch (IOException e) {
            throw new BusinessException(e.getMessage());
        }

        HashSet<?> rawSet;
        try {
            rawSet = objectMapper.readValue(in, HashSet.class);
        } catch (IOException e) {
            logger.error(
                    "An error occurred when parse the file contents with object mapper {}",
                    e.getMessage()
            );

            return;
        }

        List<CrowPermissionResource> resourcesList = DozerUtils.mapList(rawSet, CrowPermissionResource.class);
        this.permissionResources = new HashSet<>(resourcesList);
        this.permissionResourcesMap = this.permissionResources.stream().collect(Collectors.toMap(
                CrowPermissionResource::getId,
                item -> item
        ));
    }

    public Set<CrowPermissionResource> getAllNodes() {
        return permissionResources;
    }

}
